package team240;

import battlecode.common.*;

public class Worker extends GroundRobot{
	RobotController myRC;
	
	MapLocation home,firstStep,secondStep,thirdStep,fourthStep,fifthStep,sixthStep,seventhStep,eighthStep;
	MapLocation[] stairLocations;
	Direction nearestBlockDirection;
	
	public Worker(RobotController inRC) {
		super(inRC);
		myRC = inRC;
		try {
			myStatus = Status.FINDHOME;
			stairLocations = new MapLocation[8];
			nearestBlockDirection = null;
			MapLocation[] archons = myRC.senseAlliedArchons();
			FluxDeposit[] deposits = myRC.senseNearbyFluxDeposits();
			for (FluxDeposit x: deposits) {
				MapLocation depositLocation = myRC.senseFluxDepositInfo(x).location;
				for (MapLocation y: archons) {
					if (depositLocation == y) {
						home = y;
						myStatus = Status.MINE;
						setStairLocations();
					}
				}
			}
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
		}
	}
	public void runWorker() {
		//main run method for the worker
		try {
			while (true) {
				//System.out.println(myStatus);
				switch(myStatus) {
				case MINE: mine(); break;
				case TRAVEL: travel(); break;
				case FINDHOME: findhome(); break;
				default: //error unrecognized status
				}
			}
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
		}
	}
	public void mine() {
		try {
			if (messagesDidNotChangeStatus()) {
				Robot enemySighted = findNearestEnemyAndTransferEnergon(myRC.senseNearbyAirRobots(),myRC.senseNearbyGroundRobots());
				if (enemySighted == null) {
					if (!myRC.isMovementActive()) {
						if (myRC.getNumBlocks() < GameConstants.WORKER_MAX_BLOCKS) {
							if (onStairs()) {
								descendStairs();
							}
							else {
								MapLocation nearestBlock = findNearestAvailableBlock();
								if (nearestBlock == null) {
									if (nearestBlockDirection == null) {
										Message askForBlockDirection = new Message();
										int[] messageInts = new int[2];
										messageInts[0] = 5;
										messageInts[1] = Clock.getRoundNum();
										askForBlockDirection.ints = messageInts;
										myRC.broadcast(askForBlockDirection);
									}
									else {
										moveInDirection(nearestBlockDirection);
									}
								}
								else {
									if (nearestBlock.isAdjacentTo(myRC.getLocation()) && myRC.senseGroundRobotAtLocation(nearestBlock)==null) {
										myRC.loadBlockFromLocation(nearestBlock);
										nearestBlockDirection = null;
									}
									else {
										moveTowardLocation(nearestBlock);
									}
								}
							}
						}
						else {
							if (getDistanceSquared(myRC.getLocation(),home) < 9) {
								MapLocation desiredLocation = home;
								MapLocation blockLocation = home;
								if (myRC.senseHeightOfLocation(home)-myRC.senseHeightOfLocation(firstStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = firstStep;
								}
								else if (myRC.senseHeightOfLocation(firstStep)-myRC.senseHeightOfLocation(secondStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = secondStep;
									blockLocation = firstStep;
								}
								else if (myRC.senseHeightOfLocation(secondStep)-myRC.senseHeightOfLocation(thirdStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = thirdStep;
									blockLocation = secondStep;
								}
								else if (myRC.senseHeightOfLocation(thirdStep)-myRC.senseHeightOfLocation(fourthStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = fourthStep;
									blockLocation = thirdStep;
								}
								else if (myRC.senseHeightOfLocation(fourthStep)-myRC.senseHeightOfLocation(fifthStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = fifthStep;
									blockLocation = fourthStep;
								}
								else if (myRC.senseHeightOfLocation(fifthStep)-myRC.senseHeightOfLocation(sixthStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = sixthStep;
									blockLocation = fifthStep;
								}
								else if (myRC.senseHeightOfLocation(sixthStep)-myRC.senseHeightOfLocation(seventhStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = seventhStep;
									blockLocation = sixthStep;
								}
								else if (myRC.senseHeightOfLocation(seventhStep)-myRC.senseHeightOfLocation(eighthStep) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = eighthStep;
									blockLocation = seventhStep;
								}
								else if (myRC.senseHeightOfLocation(eighthStep)-myRC.senseHeightOfLocation(eighthStep.add(Direction.WEST)) <= GameConstants.WORKER_MAX_HEIGHT_DELTA) {
									desiredLocation = eighthStep.add(Direction.WEST);
									blockLocation = eighthStep;
								}
								else {
									System.out.println("Run out of room for stairs");
								}
								if (myRC.getLocation()==desiredLocation) {
									if (myRC.canUnloadBlockToLocation(blockLocation)) {
										myRC.unloadBlockToLocation(blockLocation);
									}
								}
								else {
									moveTowardLocation(desiredLocation);
								}
							}
							else {
								moveTowardLocation(home);
							}
						}
					}
				}
				else {
					//enemy sighted code
				}
			}
			myRC.yield();
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
		}
	}
	public boolean onStairs() {
		try {
			MapLocation myLocation = myRC.getLocation();
			if (myRC.senseHeightOfLocation(myLocation) < 1) {
				return false;
			}
			else {
				for (MapLocation x: stairLocations) {
					if (x == myLocation) {
						return true;
					}
				}
			}
			return false;
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
			return false;
		}
	}
	public void descendStairs() {
		try {
			MapLocation myLocation = myRC.getLocation();
			if (myLocation == firstStep) {
				if (myRC.canMove(Direction.EAST)) {
					if (myRC.getDirection() == Direction.EAST) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.EAST);
					}
				}
				else {
					//hardcode all 5 possible squares
					moveOneInDirection(Direction.NORTH_WEST);
				}
			}
			else if (myLocation == secondStep) {
				if (myRC.canMove(Direction.EAST)) {
					if (myRC.getDirection() == Direction.EAST) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.EAST);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.NORTH);
				}
			}
			else if (myLocation == thirdStep) {
				if (myRC.canMove(Direction.SOUTH)) {
					if (myRC.getDirection() == Direction.SOUTH) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.SOUTH);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.NORTH_EAST);
				}
			}
			else if (myLocation == fourthStep) {
				if (myRC.canMove(Direction.SOUTH)) {
					if (myRC.getDirection() == Direction.SOUTH) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.SOUTH);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.EAST);
				}
			}
			else if (myLocation == fifthStep) {
				if (myRC.canMove(Direction.WEST)) {
					if (myRC.getDirection() == Direction.WEST) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.WEST);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.SOUTH_EAST);
				}
			}
			else if (myLocation == sixthStep) {
				if (myRC.canMove(Direction.WEST)) {
					if (myRC.getDirection() == Direction.WEST) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.WEST);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.SOUTH);
				}
			}
			else if (myLocation == seventhStep) {
				if (myRC.canMove(Direction.NORTH)) {
					if (myRC.getDirection() == Direction.NORTH) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.NORTH);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.SOUTH_WEST);
				}
			}
			else {
				if (myRC.canMove(Direction.WEST)) {
					if (myRC.getDirection() == Direction.WEST) {
						myRC.moveForward();
					}
					else {
						myRC.setDirection(Direction.WEST);
					}
				}
				else {
					//hardcode all possible squares
					moveOneInDirection(Direction.WEST);
				}
			}
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
		}
	}
	public MapLocation findNearestAvailableBlock() {
		MapLocation myLocation = myRC.getLocation();
		int lowest = 100;
		MapLocation closest = null;
		MapLocation[] nearbyBlocks = myRC.senseNearbyBlocks();
		for (MapLocation x: nearbyBlocks) {
			boolean isNotOnStairs = true;
			for (MapLocation y: stairLocations) {
				if (x == y) {
					isNotOnStairs = false;
				}
			}
			if (isNotOnStairs) {
				int blockDistance = getDistanceSquared(myLocation,x);
				if (blockDistance < lowest) {
					closest = x;
					lowest = blockDistance;
				}
			}
		}
		return closest;
	}
	public void travel() {
		myRC.yield();
	}
	public void findhome() {
		try {
			if (messagesDidNotChangeStatus()) {
				Robot enemySighted = findNearestEnemyAndTransferEnergon(myRC.senseNearbyAirRobots(),myRC.senseNearbyGroundRobots());
				if (enemySighted == null) {
					if (!myRC.isMovementActive()) {
						if (myRC.getNumBlocks() < GameConstants.WORKER_MAX_BLOCKS) {
							MapLocation[] nearbyBlocks = myRC.senseNearbyBlocks();
							if (nearbyBlocks.length > 0) {
								MapLocation nearestBlock = getClosestLocation(nearbyBlocks);
								if (nearestBlock.isAdjacentTo(myRC.getLocation()) && myRC.senseGroundRobotAtLocation(nearestBlock)==null) {
									myRC.loadBlockFromLocation(nearestBlock);
								}
								else {
									moveTowardLocation(nearestBlock);
								}
							}
							else {
								moveTowardLocation(getClosestLocation(myRC.senseAlliedArchons()));
							}
							
						}
						else {
							moveTowardLocation(getClosestLocation(myRC.senseAlliedArchons()));
						}
					}
				}
				else {
					//enemy sighted code
				}
			}
			myRC.yield();
		}catch(Exception e) {
			System.out.println("caught exception:");
			e.printStackTrace();
		}
	}
	public void setStairLocations() {
		firstStep = home.add(Direction.NORTH_WEST);
		stairLocations[0] = firstStep;
		secondStep = home.add(Direction.NORTH);
		stairLocations[1] = secondStep;
		thirdStep = home.add(Direction.NORTH_EAST);
		stairLocations[2] = thirdStep;
		fourthStep = home.add(Direction.EAST);
		stairLocations[3] = fourthStep;
		fifthStep = home.add(Direction.SOUTH_EAST);
		stairLocations[4] = fifthStep;
		sixthStep = home.add(Direction.SOUTH);
		stairLocations[5] = sixthStep;
		seventhStep = home.add(Direction.SOUTH_WEST);
		stairLocations[6] = seventhStep;
		eighthStep = home.add(Direction.WEST);
		stairLocations[7] = eighthStep;
	}
	public boolean messagesDidNotChangeStatus() {
		//message int index: 1-enemy sighted 4-found home 6-receiving direction toward blocks from mining archon
		boolean statusNotChanged = true;
		Message[] newMessages = myRC.getAllMessages();
		for (Message k: newMessages) {
			if (messageValidated(k)) {
				switch (k.ints[0]) {
				case 4: home = k.locations[0];
					myStatus = Status.MINE;
					statusNotChanged = false; break;
				case 6: nearestBlockDirection = Direction.valueOf(k.strings[0]); break;
				default: //error unrecognized integer message indicator
				}
			}
		}
		return statusNotChanged;
	}
}
